<!-- HTML header for doxygen 1.8.6-->
<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN" "http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd">
<html xmlns="http://www.w3.org/1999/xhtml">
<head>
<meta http-equiv="Content-Type" content="text/xhtml;charset=UTF-8"/>
<meta http-equiv="X-UA-Compatible" content="IE=9"/>
<meta name="generator" content="Doxygen 1.8.13"/>
<title>OpenCV: Contours : More Functions</title>
<link href="../../opencv.ico" rel="shortcut icon" type="image/x-icon" />
<link href="../../tabs.css" rel="stylesheet" type="text/css"/>
<script type="text/javascript" src="../../jquery.js"></script>
<script type="text/javascript" src="../../dynsections.js"></script>
<script type="text/javascript" src="../../tutorial-utils.js"></script>
<link href="../../search/search.css" rel="stylesheet" type="text/css"/>
<script type="text/javascript" src="../../search/searchdata.js"></script>
<script type="text/javascript" src="../../search/search.js"></script>
<script type="text/x-mathjax-config">
  MathJax.Hub.Config({
    extensions: ["tex2jax.js", "TeX/AMSmath.js", "TeX/AMSsymbols.js"],
    jax: ["input/TeX","output/HTML-CSS"],
});
//<![CDATA[
MathJax.Hub.Config(
{
  TeX: {
      Macros: {
          matTT: [ "\\[ \\left|\\begin{array}{ccc} #1 & #2 & #3\\\\ #4 & #5 & #6\\\\ #7 & #8 & #9 \\end{array}\\right| \\]", 9],
          fork: ["\\left\\{ \\begin{array}{l l} #1 & \\mbox{#2}\\\\ #3 & \\mbox{#4}\\\\ \\end{array} \\right.", 4],
          forkthree: ["\\left\\{ \\begin{array}{l l} #1 & \\mbox{#2}\\\\ #3 & \\mbox{#4}\\\\ #5 & \\mbox{#6}\\\\ \\end{array} \\right.", 6],
          forkfour: ["\\left\\{ \\begin{array}{l l} #1 & \\mbox{#2}\\\\ #3 & \\mbox{#4}\\\\ #5 & \\mbox{#6}\\\\ #7 & \\mbox{#8}\\\\ \\end{array} \\right.", 8],
          vecthree: ["\\begin{bmatrix} #1\\\\ #2\\\\ #3 \\end{bmatrix}", 3],
          vecthreethree: ["\\begin{bmatrix} #1 & #2 & #3\\\\ #4 & #5 & #6\\\\ #7 & #8 & #9 \\end{bmatrix}", 9],
          cameramatrix: ["#1 = \\begin{bmatrix} f_x & 0 & c_x\\\\ 0 & f_y & c_y\\\\ 0 & 0 & 1 \\end{bmatrix}", 1],
          distcoeffs: ["(k_1, k_2, p_1, p_2[, k_3[, k_4, k_5, k_6 [, s_1, s_2, s_3, s_4[, \\tau_x, \\tau_y]]]]) \\text{ of 4, 5, 8, 12 or 14 elements}"],
          distcoeffsfisheye: ["(k_1, k_2, k_3, k_4)"],
          hdotsfor: ["\\dots", 1],
          mathbbm: ["\\mathbb{#1}", 1],
          bordermatrix: ["\\matrix{#1}", 1]
      }
  }
}
);
//]]>
</script><script type="text/javascript" src="https://cdnjs.cloudflare.com/ajax/libs/mathjax/2.7.0/MathJax.js"></script>
<link href="../../doxygen.css" rel="stylesheet" type="text/css" />
<link href="../../stylesheet.css" rel="stylesheet" type="text/css"/>
</head>
<body>
<div id="top"><!-- do not remove this div, it is closed by doxygen! -->
<div id="titlearea">
<!--#include virtual="/google-search.html"-->
<table cellspacing="0" cellpadding="0">
 <tbody>
 <tr style="height: 56px;">
  <td id="projectlogo"><img alt="Logo" src="../../opencv-logo-small.png"/></td>
  <td style="padding-left: 0.5em;">
   <div id="projectname">OpenCV
   &#160;<span id="projectnumber">4.5.2</span>
   </div>
   <div id="projectbrief">Open Source Computer Vision</div>
  </td>
 </tr>
 </tbody>
</table>
</div>
<!-- end header part -->
<!-- Generated by Doxygen 1.8.13 -->
<script type="text/javascript">
var searchBox = new SearchBox("searchBox", "../../search",false,'Search');
</script>
<script type="text/javascript" src="../../menudata.js"></script>
<script type="text/javascript" src="../../menu.js"></script>
<script type="text/javascript">
$(function() {
  initMenu('../../',true,false,'search.php','Search');
  $(document).ready(function() { init_search(); });
});
</script>
<div id="main-nav"></div>
<!-- window showing the filter options -->
<div id="MSearchSelectWindow"
     onmouseover="return searchBox.OnSearchSelectShow()"
     onmouseout="return searchBox.OnSearchSelectHide()"
     onkeydown="return searchBox.OnSearchSelectKey(event)">
</div>

<!-- iframe showing the search results (closed by default) -->
<div id="MSearchResultsWindow">
<iframe src="javascript:void(0)" frameborder="0" 
        name="MSearchResults" id="MSearchResults">
</iframe>
</div>

<div id="nav-path" class="navpath">
  <ul>
<li class="navelem"><a class="el" href="../../d6/d00/tutorial_py_root.html">OpenCV-Python Tutorials</a></li><li class="navelem"><a class="el" href="../../d2/d96/tutorial_py_table_of_contents_imgproc.html">Image Processing in OpenCV</a></li><li class="navelem"><a class="el" href="../../d3/d05/tutorial_py_table_of_contents_contours.html">Contours in OpenCV</a></li>  </ul>
</div>
</div><!-- top -->
<div class="header">
  <div class="headertitle">
<div class="title">Contours : More Functions </div>  </div>
</div><!--header-->
<div class="contents">
<div class="textblock"><h2>Goal </h2>
<p>In this chapter, we will learn about</p><ul>
<li>Convexity defects and how to find them.</li>
<li>Finding shortest distance from a point to a polygon</li>
<li>Matching different shapes</li>
</ul>
<h2>Theory and Code </h2>
<h3>1. Convexity Defects</h3>
<p>We saw what is convex hull in second chapter about contours. Any deviation of the object from this hull can be considered as convexity defect.</p>
<p>OpenCV comes with a ready-made function to find this, <b><a class="el" href="../../d3/dc0/group__imgproc__shape.html#gada4437098113fd8683c932e0567f47ba" title="Finds the convexity defects of a contour. ">cv.convexityDefects()</a></b>. A basic function call would look like below: </p><div class="fragment"><div class="line">hull = <a class="code" href="../../d3/dc0/group__imgproc__shape.html#ga014b28e56cb8854c0de4a211cb2be656">cv.convexHull</a>(cnt,returnPoints = <span class="keyword">False</span>)</div><div class="line">defects = <a class="code" href="../../d3/dc0/group__imgproc__shape.html#gada4437098113fd8683c932e0567f47ba">cv.convexityDefects</a>(cnt,hull)</div></div><!-- fragment --><dl class="section note"><dt>Note</dt><dd>Remember we have to pass returnPoints = False while finding convex hull, in order to find convexity defects.</dd></dl>
<p>It returns an array where each row contains these values - <b>[ start point, end point, farthest point, approximate distance to farthest point ]</b>. We can visualize it using an image. We draw a line joining start point and end point, then draw a circle at the farthest point. Remember first three values returned are indices of cnt. So we have to bring those values from cnt.</p>
<div class="fragment"><div class="line"><span class="keyword">import</span> cv2 <span class="keyword">as</span> cv</div><div class="line"><span class="keyword">import</span> numpy <span class="keyword">as</span> np</div><div class="line"></div><div class="line">img = <a class="code" href="../../d4/da8/group__imgcodecs.html#ga288b8b3da0892bd651fce07b3bbd3a56">cv.imread</a>(<span class="stringliteral">&#39;star.jpg&#39;</span>)</div><div class="line">img_gray = <a class="code" href="../../d8/d01/group__imgproc__color__conversions.html#ga397ae87e1288a81d2363b61574eb8cab">cv.cvtColor</a>(img,cv.COLOR_BGR2GRAY)</div><div class="line">ret,thresh = <a class="code" href="../../d7/d1b/group__imgproc__misc.html#gae8a4a146d1ca78c626a53577199e9c57">cv.threshold</a>(img_gray, 127, 255,0)</div><div class="line">contours,hierarchy = <a class="code" href="../../d3/dc0/group__imgproc__shape.html#gae4156f04053c44f886e387cff0ef6e08">cv.findContours</a>(thresh,2,1)</div><div class="line">cnt = contours[0]</div><div class="line"></div><div class="line">hull = <a class="code" href="../../d3/dc0/group__imgproc__shape.html#ga014b28e56cb8854c0de4a211cb2be656">cv.convexHull</a>(cnt,returnPoints = <span class="keyword">False</span>)</div><div class="line">defects = <a class="code" href="../../d3/dc0/group__imgproc__shape.html#gada4437098113fd8683c932e0567f47ba">cv.convexityDefects</a>(cnt,hull)</div><div class="line"></div><div class="line"><span class="keywordflow">for</span> i <span class="keywordflow">in</span> range(defects.shape[0]):</div><div class="line">    s,e,f,d = defects[i,0]</div><div class="line">    start = tuple(cnt[s][0])</div><div class="line">    end = tuple(cnt[e][0])</div><div class="line">    far = tuple(cnt[f][0])</div><div class="line">    <a class="code" href="../../d6/d6e/group__imgproc__draw.html#ga7078a9fae8c7e7d13d24dac2520ae4a2">cv.line</a>(img,start,end,[0,255,0],2)</div><div class="line">    <a class="code" href="../../d6/d6e/group__imgproc__draw.html#gaf10604b069374903dbd0f0488cb43670">cv.circle</a>(img,far,5,[0,0,255],-1)</div><div class="line"></div><div class="line"><a class="code" href="../../df/d24/group__highgui__opengl.html#gaae7e90aa3415c68dba22a5ff2cefc25d">cv.imshow</a>(<span class="stringliteral">&#39;img&#39;</span>,img)</div><div class="line"><a class="code" href="../../d7/dfc/group__highgui.html#ga5628525ad33f52eab17feebcfba38bd7">cv.waitKey</a>(0)</div><div class="line"><a class="code" href="../../d7/dfc/group__highgui.html#ga6b7fc1c1a8960438156912027b38f481">cv.destroyAllWindows</a>()</div></div><!-- fragment --><p> And see the result:</p>
<div class="image">
<img src="../../defects.jpg" alt="defects.jpg"/>
<div class="caption">
image</div></div>
 <h3>2. Point Polygon Test</h3>
<p>This function finds the shortest distance between a point in the image and a contour. It returns the distance which is negative when point is outside the contour, positive when point is inside and zero if point is on the contour.</p>
<p>For example, we can check the point (50,50) as follows: </p><div class="fragment"><div class="line">dist = <a class="code" href="../../d3/dc0/group__imgproc__shape.html#ga1a539e8db2135af2566103705d7a5722">cv.pointPolygonTest</a>(cnt,(50,50),<span class="keyword">True</span>)</div></div><!-- fragment --><p> In the function, third argument is measureDist. If it is True, it finds the signed distance. If False, it finds whether the point is inside or outside or on the contour (it returns +1, -1, 0 respectively).</p>
<dl class="section note"><dt>Note</dt><dd>If you don't want to find the distance, make sure third argument is False, because, it is a time consuming process. So, making it False gives about 2-3X speedup.</dd></dl>
<h3>3. Match Shapes</h3>
<p>OpenCV comes with a function <b><a class="el" href="../../d3/dc0/group__imgproc__shape.html#gaadc90cb16e2362c9bd6e7363e6e4c317" title="Compares two shapes. ">cv.matchShapes()</a></b> which enables us to compare two shapes, or two contours and returns a metric showing the similarity. The lower the result, the better match it is. It is calculated based on the hu-moment values. Different measurement methods are explained in the docs. </p><div class="fragment"><div class="line"><span class="keyword">import</span> cv2 <span class="keyword">as</span> cv</div><div class="line"><span class="keyword">import</span> numpy <span class="keyword">as</span> np</div><div class="line"></div><div class="line">img1 = <a class="code" href="../../d4/da8/group__imgcodecs.html#ga288b8b3da0892bd651fce07b3bbd3a56">cv.imread</a>(<span class="stringliteral">&#39;star.jpg&#39;</span>,0)</div><div class="line">img2 = <a class="code" href="../../d4/da8/group__imgcodecs.html#ga288b8b3da0892bd651fce07b3bbd3a56">cv.imread</a>(<span class="stringliteral">&#39;star2.jpg&#39;</span>,0)</div><div class="line"></div><div class="line">ret, thresh = <a class="code" href="../../d7/d1b/group__imgproc__misc.html#gae8a4a146d1ca78c626a53577199e9c57">cv.threshold</a>(img1, 127, 255,0)</div><div class="line">ret, thresh2 = <a class="code" href="../../d7/d1b/group__imgproc__misc.html#gae8a4a146d1ca78c626a53577199e9c57">cv.threshold</a>(img2, 127, 255,0)</div><div class="line">contours,hierarchy = <a class="code" href="../../d3/dc0/group__imgproc__shape.html#gae4156f04053c44f886e387cff0ef6e08">cv.findContours</a>(thresh,2,1)</div><div class="line">cnt1 = contours[0]</div><div class="line">contours,hierarchy = <a class="code" href="../../d3/dc0/group__imgproc__shape.html#gae4156f04053c44f886e387cff0ef6e08">cv.findContours</a>(thresh2,2,1)</div><div class="line">cnt2 = contours[0]</div><div class="line"></div><div class="line">ret = <a class="code" href="../../d3/dc0/group__imgproc__shape.html#gaadc90cb16e2362c9bd6e7363e6e4c317">cv.matchShapes</a>(cnt1,cnt2,1,0.0)</div><div class="line"><a class="code" href="../../df/d57/namespacecv_1_1dnn.html#a701210a0203f2786cbfd04b2bd56da47">print</a>( ret )</div></div><!-- fragment --><p> I tried matching shapes with different shapes given below:</p>
<div class="image">
<img src="../../matchshapes.jpg" alt="matchshapes.jpg"/>
<div class="caption">
image</div></div>
<p> I got following results:</p>
<ul>
<li>Matching Image A with itself = 0.0</li>
<li>Matching Image A with Image B = 0.001946</li>
<li>Matching Image A with Image C = 0.326911</li>
</ul>
<p>See, even image rotation doesn't affect much on this comparison.</p>
<dl class="section note"><dt>Note</dt><dd><a href="http://en.wikipedia.org/wiki/Image_moment#Rotation_invariant_moments">Hu-Moments</a> are seven moments invariant to translation, rotation and scale. Seventh one is skew-invariant. Those values can be found using <b><a class="el" href="../../d3/dc0/group__imgproc__shape.html#gab001db45c1f1af6cbdbe64df04c4e944" title="Calculates seven Hu invariants. ">cv.HuMoments()</a></b> function.</dd></dl>
<h1>Additional Resources </h1>
<h2>Exercises </h2>
<ol type="1">
<li>Check the documentation for <b><a class="el" href="../../d3/dc0/group__imgproc__shape.html#ga1a539e8db2135af2566103705d7a5722" title="Performs a point-in-contour test. ">cv.pointPolygonTest()</a></b>, you can find a nice image in Red and Blue color. It represents the distance from all pixels to the white curve on it. All pixels inside curve is blue depending on the distance. Similarly outside points are red. Contour edges are marked with White. So problem is simple. Write a code to create such a representation of distance.</li>
<li>Compare images of digits or letters using <b><a class="el" href="../../d3/dc0/group__imgproc__shape.html#gaadc90cb16e2362c9bd6e7363e6e4c317" title="Compares two shapes. ">cv.matchShapes()</a></b>. ( That would be a simple step towards OCR ) </li>
</ol>
</div></div><!-- contents -->
<!-- HTML footer for doxygen 1.8.6-->
<!-- start footer part -->
<hr class="footer"/><address class="footer"><small>
Generated on Fri Apr 2 2021 11:36:37 for OpenCV by &#160;<a href="http://www.doxygen.org/index.html">
<img class="footer" src="../../doxygen.png" alt="doxygen"/>
</a> 1.8.13
</small></address>
<script type="text/javascript">
//<![CDATA[
addTutorialsButtons();
//]]>
</script>
</body>
</html>
